package gamelogic

import (
	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/protoc/pb"
	"server_cluster/common/tools"
	"server_cluster/logic/sharemem"
	"slices"
	"sort"
	"time"
)

// AcceptQuest 接取任务
func AcceptQuest(user *sharemem.User) int32 {
	start := tools.TimeNowObj()
	logger.Debug("[AcceptQuest] start, uid: %v", user.GetUid())
	parentQuestIdList := make([]int32, 0)
	for _, mainParentQuestConfig := range gdconf.GetConfigParentQuestMap() {
		// 只接取主线任务和支线任务
		if mainParentQuestConfig.Type != config.QUEST_TYPE_MAIN && mainParentQuestConfig.Type != config.QUEST_TYPE_SIDE {
			continue
		}
		// 任务已接取
		parentQuest := user.GetParentQuest(mainParentQuestConfig.Id)
		if parentQuest != nil {
			if user.CheckParentFinish(mainParentQuestConfig.Id) {
				user.DeleteParentQuest(parentQuest)
			}
			continue
		}
		if user.CheckParentFinish(mainParentQuestConfig.Id) {
			continue
		}
		// 任务接取条件判断
		accept := true
		// &&
		for _, acceptCond := range mainParentQuestConfig.AcceptCondList {
			switch acceptCond[0] {
			case sharemem.QUEST_ACCEPT_COND_TYPE_FINISH_PARENT_QUEST:
				if !user.CheckParentFinish(acceptCond[1]) {
					accept = false
					break
				}
			case sharemem.QUEST_ACCEPT_COND_TYPE_PLAYER_LEVEL:
				if int32(user.Level) < acceptCond[1] {
					accept = false
					break
				}
			case sharemem.QUEST_ACCEPT_COND_TYPE_FINISH_QUEST:
				questConfig := gdconf.GetConfigQuest(acceptCond[1])
				if questConfig == nil {
					accept = false
					break
				}
				if !user.CheckSubQuestFinish(questConfig.Id) {
					accept = false
					break
				}
			}
		}
		if accept {
			// 接取任务
			logger.Debug("[AcceptQuest] parent quest id: %v, uid: %v", mainParentQuestConfig.Id, user.GetUid())
			user.AddParentQuest(mainParentQuestConfig.Id)
			parentQuestIdList = append(parentQuestIdList, mainParentQuestConfig.Id)
		}
	}

	for _, id := range parentQuestIdList {
		// 父任务接取事件
		handleParentQuestAccept(id, true, user)
		var pParentQuest = user.GetParentQuest(id)
		if pParentQuest == nil {
			continue
		}
		// 子任务接取事件
		handleQuestAccept(pParentQuest.CurrQuestId, true, user)
		// 触发
		var curQuest = user.GetSubQuest(id, pParentQuest.CurrQuestId)
		if curQuest == nil {
			continue
		}
		for _, cond := range curQuest.CondList {
			TriggerQuest(user, cond.Type, true)
		}
	}

	// 通知客户端
	for _, id := range parentQuestIdList {
		parentQuestConfig := gdconf.GetConfigParentQuest(id)
		if parentQuestConfig == nil {
			logger.Error("get parentQuestConfig is nil, parentQuestId: %v", id)
			continue
		}

		var pParentQuest = user.GetParentQuest(id)
		if pParentQuest == nil {
			continue
		}
		var curQuest = user.GetSubQuest(id, pParentQuest.CurrQuestId)
		if curQuest == nil {
			continue
		}
		SendMsg(config.SC_ParentQuestUpdateNtf, &pb.SC_ParentQuestUpdateNtf{
			QuestType: parentQuestConfig.Type,
			ParentQuest: &pb.ParentQuest{
				ParentQuestId: id,
				State:         pParentQuest.State,
				Quest:         user.PacketQuest(curQuest)},
			ItemList: nil,
		}, nil, user)

		SendMsg(config.SC_QuestUpdateNtf, &pb.SC_QuestUpdateNtf{
			QuestType:     parentQuestConfig.Type,
			ParentQuestId: id,
			Quest:         user.PacketQuest(curQuest),
			ItemList:      nil,
		}, nil, user)
	}
	since := time.Since(start)
	logger.Debug("[AcceptQuest] finish, costTime: %v, uid: %v", since, user.GetUid())
	return config.OK
}

// RefreshDailyQuest 刷新每日任务
func RefreshDailyQuest(user *sharemem.User) int32 {
	if !user.UserQuest.DailyQuestUnlock {
		return config.OK
	}
	nowOffset := tools.ParseTimeToObj(sharemem.MyShm.TimeNow).Add(-(time.Hour * sharemem.RefreshDailyQuestHourOffset))
	lastOffset := time.Unix(user.UserQuest.LastDailyQuestRefreshTime, 0).Add(-(time.Hour * sharemem.RefreshDailyQuestHourOffset))
	if nowOffset.Year() == lastOffset.Year() && nowOffset.YearDay() <= lastOffset.YearDay() {
		return config.OK
	}
	user.UserQuest.LastDailyQuestRefreshTime = sharemem.MyShm.TimeNow
	start := tools.TimeNowObj()
	logger.Debug("[RefreshDailyQuest] start, uid: %v", user.GetUid())
	// 清除当前每日任务
	for i := 0; i < len(user.UserQuest.DailyQuestList); i++ {
		parentQuest := &(user.UserQuest.DailyQuestList[i])
		if parentQuest.ParentQuestId == 0 {
			continue
		}
		parentQuestConfig := gdconf.GetConfigParentQuest(parentQuest.ParentQuestId)
		if parentQuestConfig == nil {
			logger.Error("get parentQuestConfig is nil, parentQuestId: %v", parentQuest.ParentQuestId)
			continue
		}
		// 设置为已完成状态让客户端删掉
		parentQuest.State = config.QUEST_STATE_FIN
		SendMsg(config.SC_ParentQuestUpdateNtf, &pb.SC_ParentQuestUpdateNtf{
			QuestType:   parentQuestConfig.Type,
			ParentQuest: user.PacketParentQuest(parentQuest),
			ItemList:    nil,
		}, nil, user)
		user.UserQuest.DailyQuestList[i].MemInit()
	}
	count := 0
	pbParentQuestList := make([]*pb.ParentQuest, 0)
	for _, mainParentQuestConfig := range gdconf.GetConfigParentQuestMap() {
		// 只接取每日任务
		if mainParentQuestConfig.Type != config.QUEST_TYPE_DAILY {
			continue
		}
		// 任务已接取
		if user.GetParentQuest(mainParentQuestConfig.Id) != nil {
			continue
		}
		// 接取任务
		logger.Debug("[RefreshDailyQuest] parent quest id: %v, uid: %v", mainParentQuestConfig.Id, user.GetUid())
		user.AddParentQuest(mainParentQuestConfig.Id)
		parentQuest := user.GetParentQuest(mainParentQuestConfig.Id)
		pbParentQuestList = append(pbParentQuestList, user.PacketParentQuest(parentQuest))
		count++
		if count >= sharemem.RefreshDailyQuestMaxNum {
			// 每日任务接取数量
			break
		}
	}
	// 通知客户端
	for _, pbParentQuest := range pbParentQuestList {
		parentQuestConfig := gdconf.GetConfigParentQuest(pbParentQuest.ParentQuestId)
		if parentQuestConfig == nil {
			logger.Error("get parentQuestConfig is nil, parentQuestId: %v", pbParentQuest.ParentQuestId)
			continue
		}
		SendMsg(config.SC_ParentQuestUpdateNtf, &pb.SC_ParentQuestUpdateNtf{
			QuestType:   parentQuestConfig.Type,
			ParentQuest: pbParentQuest,
			ItemList:    nil,
		}, nil, user)
	}
	for _, pbParentQuest := range pbParentQuestList {
		// 父任务接取事件
		handleParentQuestAccept(pbParentQuest.ParentQuestId, true, user)
		// 子任务接取事件
		handleQuestAccept(pbParentQuest.Quest.QuestId, true, user)
		// 触发
		for _, cond := range pbParentQuest.Quest.CondList {
			TriggerQuest(user, cond.CondType, true)
		}
	}
	since := time.Since(start)
	logger.Debug("[RefreshDailyQuest] finish, costTime: %v, uid: %v", since, user.GetUid())
	return config.OK
}

// TriggerQuestCond 触发任务完成条件
func TriggerQuestCond(questCondList []*sharemem.QuestCond, questConfig *gdconf.ConfigQuest, cond int32, param []int32, user *sharemem.User) {
	for condIdx, questCond := range questCondList {
		if questCond.Type != cond {
			continue
		}
		// 任务完成条件判断
		switch cond {
		case sharemem.QUEST_FINISH_COND_TYPE_FINISH_TALK:
			if len(param) < 1 || param[0] != questConfig.CondList[condIdx][1] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
		case sharemem.QUEST_FINISH_COND_TYPE_FINISH_PLOT:
			if len(param) < 1 || param[0] != questConfig.CondList[condIdx][1] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
		case sharemem.QUEST_FINISH_COND_TYPE_ENTER_SCENE:
			if len(param) < 1 || param[0] != questConfig.CondList[condIdx][1] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
		case sharemem.QUEST_FINISH_COND_TYPE_FINISH_FIGHT:
			if len(param) < 1 || param[0] != questConfig.CondList[condIdx][1] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
		case sharemem.QUEST_FINISH_COND_TYPE_SCENE_INTERACT:
			if len(param) < 2 || param[0] != questConfig.CondList[condIdx][1] || param[1] != questConfig.CondList[condIdx][2] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = questConfig.CondList[condIdx][2]
		case sharemem.QUEST_FINISH_COND_TYPE_FINISH_PARENT_QUEST:
			if len(param) < 1 || param[0] != questConfig.CondList[condIdx][1] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]

			if questCond.ParamList[0] != questConfig.CondList[condIdx][1] {
				if user.CheckParentFinish(questConfig.CondList[condIdx][1]) {
					questCond.ParamList[0] = questConfig.CondList[condIdx][1]
				}
			}
		case sharemem.QUEST_FINISH_COND_TYPE_HAVE_ITEM:
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = user.GetItemCount(questConfig.CondList[condIdx][1])
		case sharemem.QUEST_FINISH_COND_TYPE_GIVE_ITEM:
			if len(param) < 2 || param[0] != questConfig.CondList[condIdx][1] || param[1] != questConfig.CondList[condIdx][2] {
				continue
			}
			ok := CostItems(map[int32]int32{param[0]: param[1]}, user)
			if !ok {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = questConfig.CondList[condIdx][2]
		case sharemem.QUEST_FINISH_COND_TYPE_PLAYER_LEVEL:
			questCond.ParamList[0] = int32(user.Level)
		case sharemem.QUEST_FINISH_COND_TYPE_FINISH_BATTLEGROUP:
			if len(param) < 1 {
				continue
			}
			if len(questConfig.CondList[condIdx][1:]) > 5 {
				logger.Error("questConfig.CondList is too long!!!!!!!")
				return
			}
			for i := 0; i < len(questCond.ParamList); i++ {
				if questCond.ParamList[i] != 0 {
					continue
				}
				questCond.ParamList[i] = param[0]
			}
		case sharemem.QUEST_FINISH_COND_TYPE_SCENE_TRIGGER:
			if len(param) < 2 || param[0] != questConfig.CondList[condIdx][1] || param[1] != questConfig.CondList[condIdx][2] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = questConfig.CondList[condIdx][2]
		case sharemem.QUEST_FINISH_COND_TYPE_TEAM_ROLE_NUM:
			maxRoleNum := 0
			for _, team := range user.GetTeamList() {
				roleNum := 0
				for _, roleId := range team.FightRoleList {
					if roleId != 0 {
						roleNum++
					}
				}
				for _, roleId := range team.AssistRoleList {
					if roleId != 0 {
						roleNum++
					}
				}
				if roleNum > maxRoleNum {
					maxRoleNum = roleNum
				}
			}
			questCond.ParamList[0] = int32(maxRoleNum)
		case sharemem.QUEST_FINISH_COND_TYPE_ROLE_UPGRADE:
			roleNum := 0
			for _, role := range user.Role {
				if role.GetId() == 0 {
					continue
				}
				if int32(role.Level) >= questConfig.CondList[condIdx][1] {
					roleNum++
				}
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = int32(roleNum)
		case sharemem.QUEST_FINISH_COND_TYPE_ROLE_PROMOTE:
			roleNum := 0
			for _, role := range user.Role {
				if role.GetId() == 0 {
					continue
				}
				if int32(role.Promote) >= questConfig.CondList[condIdx][1] {
					roleNum++
				}
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = int32(roleNum)
		case sharemem.QUEST_FINISH_COND_TYPE_ROLE_STAR:
			roleNum := 0
			for _, role := range user.Role {
				if role.GetId() == 0 {
					continue
				}
				if int32(role.Star) >= questConfig.CondList[condIdx][1] {
					roleNum++
				}
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = int32(roleNum)
		case sharemem.QUEST_FINISH_COND_TYPE_BUILD_EQUIP:
			if len(param) < 1 {
				continue
			}
			questCond.ParamList[0] = questCond.ParamList[0] + param[0]
		case sharemem.QUEST_FINISH_COND_TYPE_HOME_SEED:
			if len(param) < 1 {
				continue
			}
			questCond.ParamList[0] = questCond.ParamList[0] + param[0]
		case sharemem.QUEST_FINISH_COND_TYPE_HOME_GATHER:
			if len(param) < 1 {
				continue
			}
			questCond.ParamList[0] = questCond.ParamList[0] + param[0]
		case sharemem.QUEST_FINISH_COND_TYPE_EQUIP_WEAR:
			maxEquipNum := 0
			for _, role := range user.Role {
				if role.GetId() == 0 {
					continue
				}
				for _, v := range role.EquipList {
					if v != 0 {
						maxEquipNum++
					}
				}
			}
			questCond.ParamList[0] = int32(maxEquipNum)
		case sharemem.QUEST_FINISH_COND_TYPE_EQUIP_UPGRADE:
			equipNum := 0
			for _, equip := range user.Equip {
				if equip.GetId() == 0 {
					continue
				}
				if int32(equip.Level) >= questConfig.CondList[condIdx][1] {
					equipNum++
				}
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = int32(equipNum)
		case sharemem.QUEST_FINISH_COND_TYPE_EQUIP_JEWEL_WEAR:
			equipNum := 0
			for _, equip := range user.Equip {
				if equip.GetId() == 0 {
					continue
				}
				jewelNum := 0
				for _, v := range equip.JewelList {
					if v != 0 {
						jewelNum++
					}
				}
				if int32(jewelNum) >= questConfig.CondList[condIdx][1] {
					equipNum++
				}
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = int32(equipNum)
		case sharemem.QUEST_FINISH_COND_TYPE_HAVE_HOME_BUILDING_FOR_LEVEL:
			var buildNum = 0
			for _, build := range user.UserHome.BuildingList {
				if !build.IsUse() {
					continue
				}
				if build.BuildingId != questConfig.CondList[condIdx][3] {
					continue
				}
				if build.Level < int8(questConfig.CondList[condIdx][2]) {
					continue
				}
				buildNum++
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = int32(buildNum)
			questCond.ParamList[2] = questConfig.CondList[condIdx][3]
		case sharemem.QUEST_FINISH_COND_TYPE_ROLE_COUNT:
			roleNum := 0
			for _, role := range user.Role {
				if role.GetId() == 0 {
					continue
				}
				roleNum++
			}
			questCond.ParamList[0] = int32(roleNum)
		case sharemem.QUEST_FINISH_COND_TYPE_WEAR_WEAPON:
			wearWeaponNum := 0
			for _, role := range user.Role {
				if role.GetId() == 0 {
					continue
				}
				if role.Weapon == 0 {
					continue
				}
				wearWeaponNum++
			}
			questCond.ParamList[0] = int32(wearWeaponNum)
		case sharemem.QUEST_FINISH_COND_TYPE_ACTIVITY_DUNGEON:
			if len(param) < 2 || param[0] != questConfig.CondList[condIdx][1] || param[1] != questConfig.CondList[condIdx][2] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = questConfig.CondList[condIdx][2]
		case sharemem.QUEST_FINISH_COND_TYPE_ACTIVITY_DUNGEON_COUNT:
			if len(param) < 2 || param[0] != questConfig.CondList[condIdx][1] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] += param[1]
			if questCond.ParamList[1] > questConfig.CondList[condIdx][2] {
				questCond.ParamList[1] = questConfig.CondList[condIdx][2]
			}
		case sharemem.QUEST_FINISH_COND_TYPE_GACHA_COUNT:
			if len(param) < 1 {
				continue
			}
			questCond.ParamList[0] = questCond.ParamList[0] + param[0]
		case sharemem.QUEST_FINISH_COND_TYPE_ROLE_WEAR_EQUIP_COUNT:
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			var roleId = questConfig.CondList[condIdx][1]
			var equipList = user.GetUserRoleEquipList(roleId)
			if equipList == nil {
				continue
			}
			questCond.ParamList[1] = int32(len(equipList))
		case sharemem.QUEST_FINISH_COND_TYPE_BUILD_EQUIP_FOR_GROUP:
			if len(param) < 2 || param[0] != questConfig.CondList[condIdx][1] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] += param[1]
			if questCond.ParamList[1] > questConfig.CondList[condIdx][2] {
				questCond.ParamList[1] = questConfig.CondList[condIdx][2]
			}
		case sharemem.QUEST_FINISH_COND_TYPE_ROLE_LEVEL:
			var role = user.GetRoleById(questConfig.CondList[condIdx][1])
			if role == nil {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = int32(role.Level)
			if questCond.ParamList[1] > questConfig.CondList[condIdx][2] {
				questCond.ParamList[1] = questConfig.CondList[condIdx][2]
			}
		case sharemem.QUEST_FINISH_COND_TYPE_AWARD_ITEM_BY_BUILDING:
			if len(param) < 2 || param[0] != questConfig.CondList[condIdx][1] {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] += param[1]
			if questCond.ParamList[1] > questConfig.CondList[condIdx][2] {
				questCond.ParamList[1] = questConfig.CondList[condIdx][2]
			}
		case sharemem.QUEST_FINISH_COND_TYPE_GADGET_STATE:
			gadget := user.GetSceneGadgetById(questConfig.CondList[condIdx][1], questConfig.CondList[condIdx][2])
			if gadget == nil {
				continue
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = questConfig.CondList[condIdx][2]
			if int32(gadget.GadgetState) == questConfig.CondList[condIdx][3] {
				questCond.ParamList[2] = questConfig.CondList[condIdx][3]
			}
		case sharemem.QUEST_FINISH_COND_TYPE_EQUIP_COUNT_BY_LEVEL:
			num := 0
			for _, equip := range user.Equip {
				if equip.GetId() == 0 {
					continue
				}
				if int32(equip.Level) < questConfig.CondList[condIdx][1] {
					continue
				}
				num++
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = int32(num)
			if questCond.ParamList[1] > questConfig.CondList[condIdx][2] {
				questCond.ParamList[1] = questConfig.CondList[condIdx][2]
			}
		case sharemem.QUEST_FINISH_COND_TYPE_WEAPON_COUNT_BY_LEVEL:
			num := 0
			for _, weapon := range user.UserWeapon.WeaponList {
				if !weapon.IsUse() {
					continue
				}
				if int32(weapon.Level) < questConfig.CondList[condIdx][1] {
					continue
				}
				num++
			}
			questCond.ParamList[0] = questConfig.CondList[condIdx][1]
			questCond.ParamList[1] = int32(num)
			if questCond.ParamList[1] > questConfig.CondList[condIdx][2] {
				questCond.ParamList[1] = questConfig.CondList[condIdx][2]
			}
		}
	}
}

// TriggerQuest 触发任务
func TriggerQuest(user *sharemem.User, cond int32, isNeedNotify bool, param ...int32) int32 {
	user.AddTriggerQuestRecDepth(1)

	questList := user.GetSubQuestList4Cond(cond)
	defer func() {
		user.SubTriggerQuestRecDepth(1)
	}()
	logger.Info("[TriggerQuest] subQuestLen :%v; cond: %v", len(*questList), cond)
	for _, quest := range *questList {
		if quest.State == config.QUEST_STATE_FIN {
			logger.Info("[TriggerQuest] skip by finish questId =%v", quest.QuestId)
			continue
		}
		if user.CheckParentFinish(quest.ParentQuestId) {
			HandleParentQuestFinish(quest.ParentQuestId, user)
			logger.Info("[TriggerQuest] skip by parentQuest finish ParentQuestId =%v", quest.ParentQuestId)
			continue
		}
		parentQuest := user.GetParentQuest(quest.ParentQuestId)
		if parentQuest == nil {
			logger.Info("[TriggerQuest] skip by parentQuest nil ParentQuestId =%v", quest.ParentQuestId)
			continue
		}
		if parentQuest.CurrQuestId != quest.QuestId {
			logger.Info("[TriggerQuest] skip by curQuest not match curQuestId=%v,questId =%v", parentQuest.CurrQuestId, quest.QuestId)
			continue
		}

		//处理进度
		parentQuestConfig := gdconf.GetConfigParentQuest(quest.ParentQuestId)
		if parentQuestConfig == nil {
			logger.Error("get parentQuestConfig is nil, parentQuestId: %v", quest.ParentQuestId)
			continue
		}
		questConfig := gdconf.GetConfigQuest(quest.QuestId)
		if questConfig == nil {
			logger.Error("get questConfig is nil, questId: %v", quest.QuestId)
			continue
		}

		questCondList := quest.GetCondList()
		oldCondParamList := make([][]int32, 0, len(questCondList))
		for _, oldCondList := range questCondList {
			oldCondParamList = append(oldCondParamList, oldCondList.GetCondParamList())
		}

		TriggerQuestCond(questCondList, questConfig, cond, param, user)
		questCondList = quest.GetCondList()
		newCondParamList := make([][]int32, 0, len(questCondList))
		for _, newCondList := range questCondList {
			newCondParamList = append(newCondParamList, newCondList.GetCondParamList())
		}

		questUpdate := !slices.EqualFunc[[][]int32](oldCondParamList, newCondParamList, func(condParamList1 []int32, condParamList2 []int32) bool {
			return slices.Equal[[]int32](condParamList1, condParamList2)
		})

		if questUpdate {
			// 通知客户端更新子任务
			SendMsg(config.SC_QuestUpdateNtf, &pb.SC_QuestUpdateNtf{
				QuestType:     parentQuestConfig.Type,
				ParentQuestId: quest.ParentQuestId,
				Quest:         user.PacketQuest(quest),
				ItemList:      nil,
			}, nil, user)
		}

		// 判断子任务是否达成条件
		questFinish := true
		for condIdx, questCond := range questCondList {
			tempCond := slices.Clone(questCond.GetCondParamList())
			condParamList := slices.Clone(questConfig.CondList[condIdx][1:])
			slices.Sort(tempCond)
			slices.Sort(condParamList)
			for condParamIdx, condParam := range tempCond {
				if condParam < condParamList[condParamIdx] {
					questFinish = false
				}
			}
		}

		if questFinish {
			logger.Info("[MarkPlayerAction FinishQuest %v %v]", quest.QuestId, user.GetUid())
			logger.Debug("quest finish, questId: %v, uid: %v", quest.QuestId, user.GetUid())
			// 子任务已完成
			quest.State = config.QUEST_STATE_FIN
			// 子任务完成执行事件
			for _, evt := range questConfig.EventList {
				ExecEvent(user, evt[0], evt[1:]...)
			}

			pbQuestItemList := make([]*pb.Item, 0)
			// 发放奖励
			if questConfig.Reward != 0 {
				// 发放奖励
				ret, itemMap, _ := RewardItem(questConfig.Reward, nil, user)
				if ret != config.OK {
					logger.Error("reward item error, ret: %v, uid: %v", ret, user.GetUid())
				}
				for itemId, itemCount := range itemMap {
					pbQuestItemList = append(pbQuestItemList, &pb.Item{
						Id:  itemId,
						Num: itemCount,
					})
				}
			}

			// 子任务完成事件
			handleQuestFinish(quest.QuestId, isNeedNotify, user)

			parentQuestFinish := true
			if quest.NextQuestId != 0 {
				parentQuestFinish = false
			}

			// 组装子任务更新数据
			sort.Slice(pbQuestItemList, func(i, j int) bool {
				return pbQuestItemList[i].Id < pbQuestItemList[j].Id
			})
			ntf := &pb.SC_QuestUpdateNtf{
				QuestType:     parentQuestConfig.Type,
				ParentQuestId: parentQuest.ParentQuestId,
				Quest:         user.PacketQuest(quest),
				ItemList:      pbQuestItemList,
			}

			if parentQuestFinish {
				// 父任务已完成
				logger.Info("[MarkPlayerAction FinishParentQuest %v %v]", parentQuest.ParentQuestId, user.GetUid())
				logger.Debug("parent quest finish, parentQuestId: %v, uid: %v", parentQuest.ParentQuestId, user.GetUid())
				parentQuest.State = config.QUEST_STATE_FIN

				// 发放奖励
				ret, itemMap, _ := RewardItem(parentQuestConfig.Reward, nil, user)
				if ret != config.OK {
					logger.Error("reward item error, ret: %v, uid: %v", ret, user.GetUid())
				}
				pbParentQuestItemList := make([]*pb.Item, 0)
				for itemId, itemCount := range itemMap {
					pbParentQuestItemList = append(pbParentQuestItemList, &pb.Item{
						Id:  itemId,
						Num: itemCount,
					})
				}

				// 通知客户端更新父任务
				sort.Slice(pbParentQuestItemList, func(i, j int) bool {
					return pbParentQuestItemList[i].Id < pbParentQuestItemList[j].Id
				})
				SendMsg(config.SC_ParentQuestUpdateNtf, &pb.SC_ParentQuestUpdateNtf{
					QuestType:   parentQuestConfig.Type,
					ParentQuest: user.PacketParentQuest(parentQuest),
					ItemList:    pbParentQuestItemList,
				}, nil, user)

				// 父任务的最后一个子任务完成 延迟通知 兼容客户端逻辑
				SendMsg(config.SC_QuestUpdateNtf, ntf, nil, user)

				// 父任务完成事件
				HandleParentQuestFinish(parentQuest.ParentQuestId, user)
			} else {
				// 兼容原本逻辑 先更新上一个子任务数据
				SendMsg(config.SC_QuestUpdateNtf, ntf, nil, user)

				currQuest := quest
				// 父任务的当前标记子任务已完成 标记下一个子任务
				var nextQuest = user.GetNextQuest(currQuest.ParentQuestId, currQuest.QuestId)

				if nextQuest != nil {
					logger.Debug("mark next quest, questId: %v, uid: %v", nextQuest.QuestId, user.GetUid())
					parentQuest.CurrQuestId = nextQuest.QuestId
					// 通知客户端添加新的子任务
					SendMsg(config.SC_QuestUpdateNtf, &pb.SC_QuestUpdateNtf{
						QuestType:     parentQuestConfig.Type,
						ParentQuestId: parentQuest.ParentQuestId,
						Quest:         user.PacketQuest(nextQuest),
					}, nil, user)

					// 子任务接取事件
					handleQuestAccept(nextQuest.QuestId, isNeedNotify, user)

					SendMsg(config.SC_ParentQuestUpdateNtf, &pb.SC_ParentQuestUpdateNtf{
						QuestType:   parentQuestConfig.Type,
						ParentQuest: user.PacketParentQuest(parentQuest),
					}, nil, user)

					// 触发
					for _, nextQuestCond := range nextQuest.GetCondList() {
						TriggerQuest(user, nextQuestCond.Type, isNeedNotify)
					}
				}
			}
		}
	}

	if user.GetTriggerQuestRecDepth() <= 1 {
		AcceptQuest(user)
	}
	return config.OK
}

func HandleParentQuestFinish(parentQuestId int32, user *sharemem.User) {
	TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_FINISH_PARENT_QUEST, true, parentQuestId)
	TriggerOpenState(user)
	TriggerUnlockBox(user, gdconf.GadgetUnlockCondFinishParentQuest, true, parentQuestId)
	//AcceptQuest(user)

	// 将完成状态记录在永久表中
	user.OnParentQuestFinish(parentQuestId)
}

// ExecEvent 执行事件
func ExecEvent(user *sharemem.User, _type int32, param ...int32) int32 {
	logger.Debug("[ExecEvent] start, type: %v, param: %v, uid: %v", _type, param, user.GetUid())
	switch _type {
	case sharemem.EVENT_EXEC_TYPE_UNLOCK_SCENE:
		sceneId := param[0]
		AddUserScene(sceneId, user)
	case sharemem.EVENT_EXEC_TYPE_CHANGE_SCENE_GADGET_STATE:
		sceneId := param[0]
		gadgetId := param[1]
		gadgetState := param[2]
		scene := user.GetSceneById(sceneId)
		if scene == nil {
			logger.Error("scene not exist, sceneId: %v", sceneId)
			return config.OK
		}
		gadget := user.GetSceneGadgetById(sceneId, gadgetId)
		if gadget == nil {
			logger.Error("gadget not exist, gadgetId: %v", gadgetId)
			return config.OK
		}
		var oldState = gadget.GadgetState
		gadget.GadgetState = int8(gadgetState)
		if user.SceneId == sceneId {
			UserSceneGadgetNotify(user, scene, gadget)
		}
		if oldState != gadget.GadgetState {
			TriggerUnlockBox(user, gdconf.GadgetUnlockCondByOtherGadget, true, 0)
			TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_SCENE_INTERACT, true, scene.SceneId, gadget.Id)
			TriggerQuest(user, sharemem.QUEST_FINISH_COND_TYPE_GADGET_STATE, true)
		}
	case sharemem.EVENT_EXEC_TYPE_UNLOCK_DAILY_QUEST:
		user.SetDailyQuestUnlock(true)
	case sharemem.EVENT_EXEC_TYPE_REWARD:
		rewardId := param[0]
		ret, _, _ := RewardItem(rewardId, nil, user)
		if ret != config.OK {
			logger.Error("reward item error, ret: %v", ret)
			return config.OK
		}
	case sharemem.EVENT_EXEC_TYPE_ENTER_SCENE:
		sceneId := param[0]
		sceneTag := param[1]
		UserTeleport(user, sceneId, sceneTag, nil)
	}
	logger.Debug("[ExecEvent] finish, uid: %v", user.GetUid())
	return config.OK
}

func TriggerOpenState(user *sharemem.User) {
	logger.Debug("[TriggerOpenState]")
	update := false
	var pbData = pb.SC_OpenFuncNtf{}
	for _, openStateConfig := range gdconf.GetOpenStateConfigMap() {
		unlock := true
		for _, condParam := range openStateConfig.CondList {
			switch condParam[0] {
			case gdconf.OpenStateCondFinishParentQuest:
				if !user.CheckParentFinish(condParam[1]) {
					unlock = false
				}
			case gdconf.OpenStateCondPlayerLevel:
				if int32(user.Level) < condParam[1] {
					unlock = false
				}
			case gdconf.OpenStateCondFinishSubQuest:
				if !user.CheckSubQuestFinish(condParam[1]) {
					unlock = false
				}
			}
		}
		if !unlock {
			continue
		}
		if user.UserQuest.CheckOpenState(openStateConfig.OpenStateId) {
			continue
		}
		user.UserQuest.UnlockOpenState(openStateConfig.OpenStateId)
		update = true
		pbData.NewFuncIdList = append(pbData.NewFuncIdList, openStateConfig.OpenStateId)
	}
	pbData.FuncIdList = user.UserQuest.GetOpenState()
	if update {
		SendMsg(config.SC_OpenFuncNtf, &pbData, nil, user)
		AcceptActivityDailyTask(user)
		AcceptActivityWeeklyTask(user)
	}
}

func handleQuestAccept(questId int32, isNeedNotify bool, user *sharemem.User) {
	TriggerAppearNpc(user, gdconf.AppearCondAcceptQuestAppear, isNeedNotify, questId)
	TriggerUnlockBox(user, gdconf.GadgetUnlockCondAcceptSubQuest, isNeedNotify, questId)
}

func handleParentQuestAccept(parentQuestId int32, isNeedNotify bool, user *sharemem.User) {
	TriggerUnlockBox(user, gdconf.GadgetUnlockCondAcceptParentQuest, isNeedNotify, parentQuestId)
}

func handleQuestFinish(questId int32, isNeedNotify bool, user *sharemem.User) {
	TriggerUnlockMonster(user, gdconf.BattleGroupUnlockCondTypeFinishQuest, questId)
	TriggerAppearNpc(user, gdconf.AppearCondFinishQuestAppear, isNeedNotify, questId)
	TriggerAppearNpc(user, gdconf.AppearCondFinishQuestDisappear, isNeedNotify, questId)
	TriggerUnlockBox(user, gdconf.GadgetUnlockCondFinishSubQuest, isNeedNotify, questId)
	TriggerUnlockCaptainSkill(questId, user)
	TriggerOpenState(user)
}
